//package com.wayhome.srpingbootmybatis.metrics.jdbc;
//
//import com.alibaba.druid.pool.DruidDataSource;
//import com.alibaba.druid.stat.JdbcDataSourceStat;
//import com.alibaba.druid.stat.JdbcResultSetStat;
//import com.alibaba.druid.stat.JdbcStatementStat;
//import io.prometheus.client.Collector;
//import io.prometheus.client.CounterMetricFamily;
//import io.prometheus.client.GaugeMetricFamily;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.BeansException;
//import org.springframework.beans.factory.config.BeanPostProcessor;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.Ordered;
//import org.springframework.core.annotation.Order;
//
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.List;
//import java.util.concurrent.ConcurrentHashMap;
//
//@Configuration
//@ConditionalOnClass({DruidDataSource.class})
//public class JdbcDatasourceMetrics {
//    private static Logger logger = LoggerFactory.getLogger(JdbcDatasourceMetrics.class);
//
//    static ConcurrentHashMap<String, DruidDataSource> druidDataSources = new ConcurrentHashMap<>();
//    @Bean
//    @Order(-100)
//    public DruidDatasourceMetricsProcessor druidDatasourceMetricsProcessor() {
//        return new DruidDatasourceMetricsProcessor();
//    }
//
//    @Bean
//    public DatasourceCollector datasourceCollector() {
//        return new DatasourceCollector();
//    }
//
//    @Bean
//    public JdbcCollector  jdbcCollector() {
//        return new JdbcCollector();
//    }
//
//    public static class DatasourceCollector extends Collector {
//        @Override
//        public List<MetricFamilySamples> collect() {
//            try {
//                List<MetricFamilySamples> mfs = new ArrayList<>();
//                GaugeMetricFamily datasourceActiveGauge = new GaugeMetricFamily("jdbc_datasource_actives", "当前活跃数", Arrays.asList("ds"));
//                GaugeMetricFamily datasourceIdleSizeGauge = new GaugeMetricFamily("jdbc_datasource_idles", "当前空闲数", Arrays.asList("ds"));
//                GaugeMetricFamily datasourceWaitThreadGauge = new GaugeMetricFamily("jdbc_datasource_waiting", "等待获取连接线程数", Arrays.asList("ds"));
//                CounterMetricFamily connectionCreateErrorCounter = new CounterMetricFamily("jdbc_datasource_create_error", "创建连接报错总数", Arrays.asList("ds"));
//                mfs.add(datasourceActiveGauge);
//                mfs.add(datasourceIdleSizeGauge);
//                mfs.add(connectionCreateErrorCounter);
//                mfs.add(datasourceWaitThreadGauge);
//                for (String name : druidDataSources.keySet()) {
//                    DruidDataSource druidDataSource = druidDataSources.get(name);
//                    datasourceActiveGauge.addMetric(Arrays.asList(name), druidDataSource.getActiveCount());
//                    datasourceIdleSizeGauge.addMetric(Arrays.asList(name), druidDataSource.getPoolingCount());
//                    datasourceWaitThreadGauge.addMetric(Arrays.asList(name), druidDataSource.getWaitThreadCount());
//                    connectionCreateErrorCounter.addMetric(Arrays.asList(name), druidDataSource.getCreateErrorCount());
//                }
//                return mfs;
//            } catch (Exception ex) {
//               logger.error("collect datasource metrics error : ",ex);
//               throw ex;
//            }
//        }
//    }
//
//
//    public static class JdbcCollector extends Collector {
//        @Override
//        public List<MetricFamilySamples> collect() {
//            try {
//                List<MetricFamilySamples> mfs = new ArrayList<>();
//                CounterMetricFamily transactionRollbackCounter = new CounterMetricFamily("jdbc_connection_rollback", "回滚事务累计次数", Arrays.asList("ds"));
//                CounterMetricFamily connectionCreateTimeCounter = new CounterMetricFamily("jdbc_connection_create_total_time", "创建连接总耗时", Arrays.asList("ds"));
//                CounterMetricFamily connectionUseTimeCount = new CounterMetricFamily("jdbc_connection_trancation_stat", "连接使用时间", Arrays.asList("ds", "type"));
//
//                CounterMetricFamily statementErrorCounter = new CounterMetricFamily("jdbc_connection_statement_error", "SQL执行错误数量累计", Arrays.asList("ds"));
//                CounterMetricFamily statementTotalCounter = new CounterMetricFamily("jdbc_connection_statement_total", "SQL执行总次数", Arrays.asList("ds"));
//                CounterMetricFamily statementTotalTimeCounter = new CounterMetricFamily("jdbc_connection_statement_total_time", "SQL执行总时间", Arrays.asList("ds"));
//                GaugeMetricFamily statementRunningCounter = new GaugeMetricFamily("jdbc_connection_statement_runing", "SQL正在执行中的数量", Arrays.asList("ds"));
//
//                CounterMetricFamily resultSetOpenCounter = new CounterMetricFamily("jdbc_connection_resultset_total", "SQL游标打开总次数", Arrays.asList("ds"));
//                GaugeMetricFamily resultSetOpeningCounter = new GaugeMetricFamily("jdbc_connection_resultset_opening", "当前打开的SQL游标", Arrays.asList("ds"));
//                CounterMetricFamily resultSetRecordCounter = new CounterMetricFamily("jdbc_connection_resultset_record_count", "SQL游标获取的总记录数量", Arrays.asList("ds"));
//                CounterMetricFamily resultSetTotalTimeCounter = new CounterMetricFamily("jdbc_connection_resultset_exec_time", "SQL游标执行总时长", Arrays.asList("ds"));
//                for (String name : druidDataSources.keySet()) {
//                    DruidDataSource druidDataSource = druidDataSources.get(name);
//                    JdbcDataSourceStat jdbcDataSourceStat = druidDataSource.getDataSourceStat();
//                    if (jdbcDataSourceStat == null) {
//                        logger.warn("the stat info is null for datasource : {} ", name);
//                        continue;
//                    }
//                    transactionRollbackCounter.addMetric(Arrays.asList(name), jdbcDataSourceStat.getConnectionStat().getRollbackCount());
//                    connectionCreateTimeCounter.addMetric(Arrays.asList(name), jdbcDataSourceStat.getConnectionStat().getConnectMillis());
//
//                    long[] buckets = jdbcDataSourceStat.getConnectionHoldHistogram().getRanges();
//                    for (int i = 0; i < buckets.length; i++) {
//                        connectionUseTimeCount.addMetric(Arrays.asList(name, "range_" + buckets[i] + "ms"), jdbcDataSourceStat.getConnectionHoldHistogram().getValue(i));
//                    }
//                    JdbcStatementStat jdbcStatementStat = jdbcDataSourceStat.getStatementStat();
//                    statementErrorCounter.addMetric(Arrays.asList(name), jdbcStatementStat.getErrorCount());
//                    statementRunningCounter.addMetric(Arrays.asList(name), jdbcStatementStat.getRunningCount());
//                    statementTotalCounter.addMetric(Arrays.asList(name), jdbcStatementStat.getExecuteCount());
//                    statementTotalTimeCounter.addMetric(Arrays.asList(name), jdbcStatementStat.getExecuteMillisTotal());
//
//                    JdbcResultSetStat jdbcResultSetStat = jdbcDataSourceStat.getResultSetStat();
//                    resultSetOpenCounter.addMetric(Arrays.asList(name), jdbcResultSetStat.getOpenCount());
//                    resultSetOpeningCounter.addMetric(Arrays.asList(name), jdbcResultSetStat.getOpeningCount());
//                    resultSetRecordCounter.addMetric(Arrays.asList(name), jdbcResultSetStat.getFetchRowCount());
//                    resultSetTotalTimeCounter.addMetric(Arrays.asList(name), jdbcResultSetStat.getAliveMillisTotal());
//                }
//                mfs.add(transactionRollbackCounter);
//                mfs.add(connectionCreateTimeCounter);
//                mfs.add(connectionUseTimeCount);
//
//                mfs.add(statementErrorCounter);
//                mfs.add(statementTotalCounter);
//                mfs.add(statementTotalTimeCounter);
//                mfs.add(statementRunningCounter);
//
//                mfs.add(resultSetOpenCounter);
//                mfs.add(resultSetOpeningCounter);
//                mfs.add(resultSetRecordCounter);
//                mfs.add(resultSetTotalTimeCounter);
//                return mfs;
//            } catch (Exception ex) {
//                logger.error("collect jdbc metrics error : ",ex);
//                throw ex;
//            }
//        }
//    }
//
//    public static class DruidDatasourceMetricsProcessor implements BeanPostProcessor, Ordered {
//        @Override
//        public int getOrder() {
//            return -100;
//        }
//
//        @Override
//        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//            try {
//                if (bean instanceof DruidDataSource) {
//                    DruidDataSource druidDataSource = (DruidDataSource) bean;
//
////                    if (druidDataSource.getDataSourceStat().getMaxSqlSize() < 3000) {
////                        druidDataSource.getDataSourceStat().setMaxSqlSize(3000);
////                    }
////                    List<Filter> filters = druidDataSource.getProxyFilters();
////                    if (filters != null && !filters.isEmpty()) {
////                        filters.stream().filter(f -> f instanceof StatFilter).forEach(f -> ((StatFilter) f).setMergeSql(true));
////                    }
//                    logger.info("datasource {} - {} ", druidDataSource.getName(), druidDataSource.toString(), druidDataSource.isInited());
//                    String databaseUrl = druidDataSource.getUrl();
//                    int begin = databaseUrl.lastIndexOf("//") + 2;
//                    int end = databaseUrl.indexOf("?") == -1 ? databaseUrl.length() : databaseUrl.indexOf("?");
//                    String name = databaseUrl.substring(begin, end);
//                    druidDataSources.putIfAbsent(name , druidDataSource);
//                }
//            } catch (Throwable throwable) {
//                logger.error("datasource metrics init error : {} ", throwable.getMessage(), throwable);
//            }
//            return bean;
//        }
//    }
//}
